// File Name: ServerSideCustomProvider.cpp

#pragma comment(lib, "oleaut32.lib")
#pragma comment(lib, "Uiautomationcore.lib")

#include "Stdafx.h"
#include "ServerSideCustomProvider.h"

namespace UIAutomationCPP
{
	ServerSideCustomProvider::ServerSideCustomProvider()
	{
		//InitializeIDs();
	}

	ServerSideCustomProvider::ServerSideCustomProvider(HWND handle)
	{
		controlHWnd = handle;
		//InitializeIDs();
	}

	ServerSideCustomProvider::~ServerSideCustomProvider()
	{
	}

	ServerSideCustomProvider& ServerSideCustomProvider::operator =(ServerSideCustomProvider& rhs)
	{
		if(this != &rhs)
			return rhs;
		return *this;
	}

	/*void ServerSideCustomProvider::InitializeIDs()
	{
		static bool inited = false;
		if (!inited)
		{
			inited = true;
			CustomIds.ValueProperty = CustomUiaIdLookup(AutomationIdentifierType_Property, &valuePropertyGuid);
			CustomIds.IsReadOnlyProperty = CustomUiaIdLookup(AutomationIdentifierType_Property, &isReadOnlyPropertyGuid);
			CustomIds.RotatePattern = CustomUiaIdLookup(AutomationIdentifierType_Pattern, &patternGuid);
			CustomIds.CustomEvent = CustomUiaIdLookup(AutomationIdentifierType_Event, &eventGuid);
		}
	}

	int ServerSideCustomProvider::CustomUiaIdLookup(AutomationIdentifierType type, GUID* pGuid)
	{
		if(type == AutomationIdentifierType_Property)
		{
			if(*pGuid == valuePropertyGuid)
				return Rotate_Value_PropertyID;
			else if(*pGuid == isReadOnlyPropertyGuid)
				return Rotate_IsReadOnly_PropertyID;
		}
		else if(type == AutomationIdentifierType_Pattern)
		{
			if(*pGuid == patternGuid)
				return Rotate_PatternID;
		}
		else if(AutomationIdentifierType_Event)
		{
			if(*pGuid == eventGuid)
				return Rotate_Reset_EventID;
		}
		else
			return 0;
	}*/

	HRESULT __stdcall ServerSideCustomProvider::GetPatternProvider(PATTERNID patternId, IUnknown** pRetVal)
	{
		if (patternId == Ids.RotatePattern)
		{
			AddRef();
			*pRetVal =(IUnknown*)(IRawElementProviderSimple*)this;
		}
		else
		{
			*pRetVal = NULL;   
		}
		return S_OK;
	}

	HRESULT __stdcall ServerSideCustomProvider::GetPropertyValue(PROPERTYID propertyId, VARIANT* pRetVal)
	{
		if (propertyId == Ids.ValueProperty)
		{
			pRetVal->vt = VT_BSTR;
			pRetVal->bstrVal = SysAllocString(L"ColorButton");
		}
		/*else if (propertyId == CustomIds.ControlTypeProperty)
		{
			pRetVal->vt = VT_I4;
			pRetVal->lVal = CustomIds.ButtonControlType;
		}*/
		else
		{
			pRetVal->vt = VT_EMPTY;
		   // UI Automation will attempt to get the property from the host window provider.
		}
		return S_OK;
	}

	HRESULT __stdcall ServerSideCustomProvider::get_HostRawElementProvider(IRawElementProviderSimple** pRetVal)
	{
		return UiaHostProviderFromHwnd(controlHWnd, pRetVal);
	}

	HRESULT __stdcall ServerSideCustomProvider::get_ProviderOptions(ProviderOptions* pRetVal)
	{
		*pRetVal = ProviderOptions_ServerSideProvider | ProviderOptions_UseComThreading;
		return S_OK;
	}

	//HRESULT WINAPI ServerSideCustomProvider::UiaRaiseAutomationEvent(IRawElementProviderSimple *pProvider, EVENTID id)
	//{
	//	//UiaRaiseAutomationEvent(pProvider, id);
	//	//if(id == Rotate_Reset_EventID)
	//	//	UiaClientsAreListening();

	//	//if(UiaClientsAreListening())
	//	//{
	//	//    IRawElementProviderSimple pProvider = new MyCustomControlProvider(hwnd, pFocusedItem);
	//	//	  UiaRaiseAutomationEvent(pProvider, UIA_FocusChangedEventId);
	//	//	  pProvider->Release();
	//	//}

	//	return 0;
	//}

	//HRESULT WINAPI ServerSideCustomProvider::UiaRaiseAutomationPropertyChangedEvent(IRawElementProviderSimple *pProvider, PROPERTYID id, VARIANT oldValue, VARIANT newValue)
	//{
	//	//UiaRaiseAutomationPropertyChangedEvent(pProvider, id, oldValue, newValue);
	//	return 0;
	//}

	//HRESULT WINAPI ServerSideCustomProvider::UiaRaiseStructureChangedEvent(IRawElementProviderSimple *pProvider, StructureChangeType structureChangeType, int *pRuntimeId, int cRuntimeIdLen)
	//{
	//	//UiaRaiseStructureChangedEvent(pProvider, structureChangeType, *pRuntimeId, cRuntimeIdLen);
	//	return 0;
	//}

	HRESULT __stdcall ServerSideCustomProvider::QueryInterface(REFIID riid, void **ppvObj)
	{
		if(riid == IID_IUnknown)
			*ppvObj =(IUnknown*)((IRawElementProviderSimple*)this);
		else if(riid == IID_IRawElementProviderSimple)
			*ppvObj =(IRawElementProviderSimple*)this;
		else
		{
			*ppvObj = NULL;
			return E_NOINTERFACE;
		}

		((IUnknown*)(*ppvObj))->AddRef();
		return S_OK;
	}

	ULONG __stdcall ServerSideCustomProvider::AddRef()
	{
		InterlockedIncrement(&refCount);
		return refCount;
	}

	ULONG __stdcall ServerSideCustomProvider::Release()
	{
		ULONG ulRefCount = InterlockedDecrement(&refCount);
		if (ulRefCount == 0)
		{
			delete this;
		}
		return ulRefCount;
	}
}
